home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / client / client.c next >
C/C++ Source or Header  |  1996-07-24  |  13KB  |  516 lines

  1. /*
  2.  * static char *rcsid_client_c =
  3.  *    "$Id: client.c,v 1.18 1996/07/24 06:58:52 master Exp master $";
  4.  */
  5.  
  6. /*
  7.     CrossFire, A Multiplayer game for X-windows
  8.  
  9.     Copyright (C) 1992 Frank Tore Johansen
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 2 of the License, or
  14.     (at your option) any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.     The author can be reached via e-mail to frankj@ifi.uio.no.
  26. */
  27.  
  28. /* include "includes.h" so all the various system identifiers
  29.  * (ie, __sgi__, __sun__, etc) are set up correctly.  A lot of
  30.  * the include files could probably be deleted below.
  31.  */
  32.  
  33. #include <includes.h>
  34. #include <config.h>
  35.  
  36. #ifdef SERVER
  37. #include <string.h>
  38. #include <ctype.h>
  39. #include <sys/types.h>
  40. #include <sys/time.h>
  41. #include <sys/socket.h>
  42. #include <netinet/in.h>
  43. #include <arpa/inet.h>
  44. #include <netdb.h>
  45. #include <stdio.h>
  46. #include <X11/Xlib.h>
  47. #include <pwd.h>
  48. #ifdef NCR
  49. #include <sys/utsname.h>
  50. #endif
  51.  
  52. #if defined(__sgi__) || defined(SVR4)
  53. #ifndef SYS_NMLN
  54. #define SYS_NMLN 257
  55. #endif
  56. #include <sys/systeminfo.h>
  57. #endif
  58. #if !defined (__STRICT_ANSI__) || defined (__sun__)
  59. # if !defined (Mips) && !defined (vax) && !defined(ibm032)
  60. #  include <stdlib.h>
  61. # endif
  62. # if !defined (MACH) && !defined (sony) && !defined (vax) && !defined(ibm032) \
  63.     && !defined (NeXT) && !defined(linux) && !defined(DMALLOC)
  64. #  include <malloc.h>
  65. # endif
  66. #endif
  67.  
  68. #ifndef NAME_MAX
  69. # ifdef _POSIX_NAME_MAX
  70. #  define     NAME_MAX        pathconf("/dev/null", _POSIX_NAME_MAX)
  71. # else
  72. #  ifdef MAXHOSTNAMELEN
  73. #   define    NAME_MAX        MAXHOSTNAMELEN
  74. #  else
  75. #   define    NAME_MAX        256
  76. #  endif
  77. # endif
  78. #endif
  79.  
  80.  
  81. #include <global.h> /* Sad to include the whole thing, only need libproto.h */
  82. #include <version.h>
  83.  
  84. #ifndef __CEXTRACT__
  85. #include "proto.h" /* My own prototyes, made by "make proto" */
  86. #endif
  87.  
  88. int
  89. main(int argc, char **argv, char **env)
  90. {
  91.   char *dispname = (char *) getenv("DISPLAY");
  92.   char localdispname[65+6];
  93.   char *hostname = (char *) getenv("HOST");
  94.   char *optcmd = (char *) NULL;
  95.   char *ch, *p, *q;
  96.   char *username;
  97.   struct passwd *pwent;
  98.   struct protoent *protox;
  99.   Display *display;
  100.   struct sockaddr_in insock;
  101.   int i;
  102.   char buf[MAX_BUF], buf2[MAX_BUF];
  103.   int fd, fd2;
  104.   FILE *fpin,*fpout;
  105.   int set_pixmaps = 0, set_xpm = 0;
  106.   int set_split = 0;
  107.   int synchronize = (-1);
  108.  
  109.   /*init_library();*/
  110.   init_globals();
  111.   init_function_pointers();
  112.   init_defaults();
  113.  
  114.   for (i = 1; i < argc; i++)
  115.   {
  116.     int l = strlen(argv[i]);
  117.     if(l > 1)
  118.     {
  119.       if (!strncmp(argv[i], "-server", l))
  120.       {
  121.         if (++i == argc)
  122.         {
  123.           fprintf(stderr, "You must specify a hostname after -server.\n");
  124.           return 1;
  125.         }
  126.         hostname = argv[i];
  127.         continue;
  128.       }
  129.       if (!strncmp(argv[i], "-display", l))
  130.       {
  131.         if (++i == argc)
  132.         {
  133.           fprintf(stderr, "You must specify the display after -display.\n");
  134.           return 1;
  135.         }
  136.         dispname = argv[i];
  137.         continue;
  138.       }
  139.       if (!strncmp(argv[i], "-debug", l))
  140.       {
  141.         debug = 1;
  142.         continue;
  143.       }
  144.       if (!strncmp(argv[i], "-cmd", l))
  145.       {
  146.         if (++i == argc)
  147.         {
  148.           fprintf(stderr, "You must specify the command to run after -cmd.\n");
  149.           return 1;
  150.         }
  151.         optcmd = argv[i];
  152.         continue;
  153.       }
  154.       if (!strncmp(argv[i], "-pix", l))
  155.       {
  156.         set_pixmaps = 1;
  157.         continue;
  158.       }
  159.       if (!strncmp(argv[i], "-xpm", l))
  160.       {
  161.         set_xpm = 1;
  162.         continue;
  163.       }
  164.       if (!strncmp(argv[i], "-split", l) || !strcmp("w", argv[i]))
  165.       {
  166.         set_split = 1;
  167.         continue;
  168.       }
  169.       if (!strncmp(argv[i], "-synchronize", l))
  170.       {
  171.         if (++i == argc || !sscanf(argv[i], "%d", &synchronize))
  172.         {
  173.           fprintf(stderr, "You must specify a number after -synchronize.\n");
  174.           return 1;
  175.         }
  176.         continue;
  177.       }
  178.       if (!strncmp(argv[i], "-help", l))
  179.         usage(argv[0]);
  180.     }
  181.     fprintf(stderr,"Unknown argument: %s.\n",argv[i]);
  182.     usage(argv[0]);
  183.   }
  184.   if (hostname == (char *) NULL)
  185.   {
  186.     fprintf(stderr, "You must set the HOST environment variable.\n");
  187.     fprintf(stderr, "(Or specify server with the -server option.)\n");
  188.     return 1;
  189.   }
  190.  
  191.   if ((pwent = getpwuid(getuid())) == (struct passwd *) NULL)
  192.   {
  193.     fprintf(stderr, "Can't find your username.\n");
  194.     return 1;
  195.   }
  196.   username = strdup_local(pwent->pw_name);
  197.  
  198.  
  199.   if (optcmd == (char *) NULL)
  200.   {
  201.     if (dispname == (char *) NULL)
  202.     {
  203.       fprintf(stderr, "You must set the DISPLAY environment variable.\n");
  204.       fprintf(stderr, "(Or specify it with the -display option.)\n");
  205.       return 1;
  206.     }
  207.     if (*dispname == ':')
  208.     {
  209.       char localhostname[65+6];
  210.  
  211. #ifdef SVR4
  212.       if (sysinfo(SI_HOSTNAME, localhostname, NAME_MAX) <0) {
  213.     fprintf(stderr, "Can't get local hostname.\n");
  214.     perror("%s: SI_HOSTNAME");
  215.       }
  216. #else   /* Assume BSD */
  217.       if (gethostname(localhostname, 65))
  218.       {
  219.     fprintf(stderr, "Can't get local hostname.\n");
  220.     perror("gethostname ");
  221.       }
  222. #endif
  223.       sprintf(localdispname, "%s%s", localhostname, dispname);
  224.       dispname = localdispname;
  225.     }
  226.  
  227.     if ((display = XOpenDisplay(dispname)) == (Display *) NULL)
  228.     {
  229.       fprintf(stderr, "Can't open display %s.\n",dispname);
  230.       return 1;
  231.     }
  232.     if (!set_pixmaps && !set_xpm && !check_font_path(display))
  233.     {
  234.       fprintf(stderr,"Trying to fix fontpath for %s.\n",dispname);
  235.       fflush(stderr);
  236.       set_font_path(display,FONTDIR);
  237.       if (!check_font_path(display))
  238.       {
  239.         fprintf(stderr,"Failed to fix the fontpath.\n");
  240.         return 1;
  241.       }
  242.     }
  243.     XCloseDisplay(display);
  244.   }
  245.  
  246.   /* End of X-stuff, over to socket-stuff... */
  247.  
  248.   protox = getprotobyname("tcp");
  249.   if (protox == (struct protoent  *) NULL)
  250.   {
  251.     fprintf(stderr, "Error getting prorobyname (tcp)\n");
  252.     return 1;
  253.   }
  254.   fd = socket(PF_INET, SOCK_STREAM, protox->p_proto);
  255.   if (fd == (-1))
  256.   {
  257.     perror("Error on socket command");
  258.     return 1;
  259.   }
  260.   insock.sin_family = AF_INET;
  261.   insock.sin_port = htons((unsigned short)PORT);
  262.   if (isdigit(*hostname))
  263.   {
  264.     insock.sin_addr.s_addr = inet_addr(hostname);
  265.     sprintf(buf,"xhost +%s",hostname);
  266.   }
  267.   else
  268.   {
  269.     struct hostent *hostbn = gethostbyname(hostname);
  270.     if (hostbn == (struct hostent *) NULL)
  271.     {
  272.       fprintf(stderr,"Unknown host: %s\n",hostname);
  273.       return 1;
  274.     }
  275. #if defined(__sun__) || defined(SVR4)
  276.     memcpy(&insock.sin_addr, hostbn->h_addr, hostbn->h_length);
  277. #else
  278.     bcopy(hostbn->h_addr, &insock.sin_addr, hostbn->h_length);
  279. #endif
  280.     sprintf(buf,"xhost +%s",hostbn->h_name);
  281.   }
  282. #ifndef SECURE    /* I don't like xhost + */
  283.   if (optcmd == (char *) NULL)
  284.   {
  285.     fprintf(stderr,"%s\n",buf);
  286.     system(buf);
  287.   }
  288. #endif
  289.   if (connect(fd,(struct sockaddr *)&insock,sizeof(insock)) == (-1))
  290.   {
  291.     perror("Can't connect to server");
  292.     return 1;
  293.   }
  294.   fd2 = dup(fd);
  295.   fpin = fdopen(fd,"r");
  296.   fpout = fdopen(fd2,"w");
  297.   fputs("version\n",fpout);
  298.   fflush(fpout);
  299.   fgets(buf, MAX_BUF-1, fpin);
  300.   if (!strncmp(buf, "Welcome",7)) {
  301.     if (fgets(buf, MAX_BUF-1, fpin)==NULL) {
  302.       fprintf(stderr,"Syntax error in remote version: %s",buf);
  303.       return 1;
  304.     }
  305.   }
  306.   if ((ch = strchr(buf, 'v')) == NULL) {
  307.       fprintf(stderr,"Syntax error in remote version: %s",buf);
  308.       return 1;
  309.   }
  310.   else
  311.   if(compare_versions(++ch))
  312.     return 1;
  313.  
  314.   fprintf(fpout,"listen 0\n");
  315.   fflush(fpout);
  316.   if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
  317.   {
  318.     fprintf(stderr, "Failed to set listen to 0: %s", buf);
  319.     return 1;
  320.   }
  321.  
  322.   fprintf(fpout,"name %s\n",username);
  323.   fflush(fpout);
  324.   if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
  325.   {
  326.     fprintf(stderr, "Failed to set name: %s", buf);
  327.     return 1;
  328.   }
  329.   if (set_xpm)
  330.   {
  331.     fputs("set xpm\n", fpout);
  332.     fflush(fpout);
  333.     if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
  334.     {
  335.       fprintf(stderr, "Failed to set XPM mode (server might not have it enabled): %s", buf);
  336.       return 1;
  337.     }
  338.   }
  339.   else if (set_pixmaps)
  340.   {
  341.     fputs("set pixmaps\n", fpout);
  342.     fflush(fpout);
  343.     if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
  344.     {
  345.       fprintf(stderr, "Failed to set pixmaps: %s", buf);
  346.       return 1;
  347.     }
  348.   }
  349.   else {
  350.     fputs("set font\n", fpout);
  351.     fflush(fpout);
  352.     if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
  353.     {
  354.       fprintf(stderr, "Failed to select font mode: %s", buf);
  355.       return 1;
  356.     }
  357.   }
  358.   if (set_split)
  359.   {
  360.     fputs("set split\n", fpout);
  361.     fflush(fpout);
  362.     if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
  363.     {
  364.       fprintf(stderr, "Failed to set split windows: %s", buf);
  365.       return 1;
  366.     }
  367.   }
  368.   if (synchronize != (-1))
  369.   {
  370.     fprintf(fpout, "synchronize %d\n", synchronize);
  371.     fflush(fpout);
  372.     if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
  373.     {
  374.       fprintf(stderr, "Failed to set synchronize: %s", buf);
  375.       return 1;
  376.     }
  377.   }
  378.   if (optcmd != NULL) {
  379.     set_protocol(fpin, fpout, 1);
  380.     strcpy (q = buf2, optcmd);
  381.     do {
  382.     if ((p = strchr (q, ';')))
  383.         *p = '\0';
  384.     fprintf(fpout,"%s\n", q);
  385.     q = p + 1;
  386.     fflush(fpout);
  387.     while(fgets(buf, MAX_BUF - 1, fpin) != NULL && strcmp(buf,"EOT\n"))
  388.         fprintf(stderr,"%s",buf);
  389.     } while (p);
  390.   }
  391.   else /* Default command is add... */
  392.   {
  393.     fprintf(fpout,"add %s\n",dispname);
  394.     fflush(fpout);
  395.     if (fgets(buf, MAX_BUF - 1, fpin) == NULL || strcmp(buf,"OK.\n"))
  396.     {
  397.       fprintf(stderr,"Failed to add %s: %s",dispname,buf);
  398.       return 1;
  399.     }
  400.   }
  401.   fputs("quit\n",fpout);
  402.   fflush(fpout);
  403.   if (fgets(buf, MAX_BUF - 1, fpin) != NULL)
  404.   {
  405.     fclose(fpin);
  406.     fclose(fpout);
  407.   }
  408.   close(fd2); /* Hmm, why do I bother... */
  409.   close(fd);
  410.   return 0;
  411. }
  412.  
  413. void
  414. set_protocol(FILE *fpin, FILE *fpout, int p)
  415. {
  416.   char buf[256];
  417.   fprintf(fpout,"protocol %d\n",p);
  418.   fflush(fpout);
  419.   if (fgets(buf, 250, fpin) == NULL || strcmp(buf,"OK.\n"))
  420.   {
  421.     fprintf(stderr,"Failed to set protocol.\n");
  422.     exit(1);
  423.   }
  424.   if (p == 1)
  425.     if(fgets(buf, 250,fpin) == NULL || strcmp(buf,"EOT\n"))
  426.     {
  427.       fprintf(stderr, "Protocol 1 out of order.\n");
  428.       exit(1);
  429.     }
  430. }
  431.  
  432. int
  433. compare_versions(char *remote_ver)
  434. {
  435. #if 1
  436.   return 0;
  437. #else
  438.   int remote_version,remote_subversion,remote_patchlevel;
  439.   int client_version,client_subversion,client_patchlevel;
  440.   int remote_sum, client_sum;
  441.  
  442.   if(sscanf(remote_ver,"%d.%d.%d",
  443.             &remote_version,&remote_subversion,&remote_patchlevel) != 3)
  444.   {
  445.     fprintf(stderr, "Failed to decode remote version: %s\n",remote_ver);
  446.     return 1;
  447.   }
  448.   sscanf(VERSION,"%d.%d",&client_version,&client_subversion);
  449.   sscanf(PATCH,".%d",&client_patchlevel);
  450.   remote_sum = remote_version*10000 + remote_subversion*100 + remote_patchlevel;
  451.   client_sum = client_version*10000 + client_subversion*100 + client_patchlevel;
  452.   if (remote_sum > client_sum)
  453.   {
  454.     fprintf(stderr,"You will need to get a newer version of crossclient,\n");
  455.     fprintf(stderr,"at least version %s (this is %s%s)\n",
  456.             remote_ver,VERSION,PATCH);
  457.     return 1;
  458.   }
  459.   if (remote_sum < client_sum)
  460.   {
  461.     fprintf(stderr,
  462.             "Warning: The remote version is older than your client version.\n");
  463.     fprintf(stderr,"(It should still be backward compatible with your font)\n");
  464.   }
  465.   return 0;
  466. #endif
  467. }
  468.  
  469. void
  470. usage(char *progname)
  471. {
  472.   char *ch = strrchr(progname, '/');
  473.   fprintf(stderr, "Usage: %s [options]\n",
  474.           (ch == (char *) NULL ? progname : ch + 1));
  475.   fprintf(stderr,"Options:\n");
  476.   fprintf(stderr,
  477.     "-server <name>   - Connect to <name> instead of \"localhost\".\n");
  478.   fprintf(stderr,
  479.     "-display <name>  - Use <name> instead of the DISPLAY environment var.\n");
  480.   fprintf(stderr,
  481.     "-pix             - Use pixmaps instead of fonts.\n");
  482.   fprintf(stderr,
  483.     "-xpm             - Use color pixmaps (XPM) instead of fonts.\n");
  484.   fprintf(stderr,
  485.     "                   Note: Some servers may not support this\n");
  486.   fprintf(stderr,
  487.     "-split           - Use split windows.\n");
  488.   fprintf(stderr,
  489.     "-cmd <command>   - Specify an other command than the default \"add\".\n");
  490.   fprintf(stderr,
  491.     "                   Try \"help\" as <command> to see what is allowed.\n");
  492.   fprintf(stderr,
  493.     "-debug           - Turn on debugging.\n");
  494.   fprintf(stderr,
  495.     "-synchronize <nr>- Specifies frequency of synchronize Vs flush.\n");
  496.   fprintf(stderr,
  497.     "-help            - Display this information.\n");
  498.   exit(0);
  499. }
  500. #else
  501. #include <stdio.h>
  502.  
  503. #ifdef __sun__
  504. int fprintf();
  505. #endif
  506.  
  507. int
  508. main(int argc, char **argv, char **env)
  509. {
  510.   (void) fprintf(stderr,
  511.                  "You have to define \"SERVER\" in include/config.h if you\n");
  512.   (void) fprintf(stderr,"want the client to work.\n");
  513.   return 0;
  514. }
  515. #endif
  516.